<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <script type="text/javascript" src="promifill.js"></script>
    <!-- <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> -->
    <script type="text/javascript">
        //window.Promise = Promifill;
        function reqAsPromise(req) {
            return new Promise(function (resolve, reject) {
                req.onsuccess = function() {
                    resolve(req);
                    Promise.flushQueue && Promise.flushQueue();
                };
                req.onerror = function(e) {
                    reject(new Error("IDB request failed: " + e.target.error.message));
                    Promise.flushQueue && Promise.flushQueue();
                };
            });
        }

        function Storage(databaseName) {
            this._databaseName = databaseName;
            this._database = null;
        }

        Storage.prototype = {
            open: function() {
                const req = window.indexedDB.open(this._databaseName);
                const self = this;
                req.onupgradeneeded = function(ev) {
                    const db = ev.target.result;
                    const oldVersion = ev.oldVersion;
                    self._createStores(db, oldVersion);
                }; 
                return reqAsPromise(req).then(function() {
                    self._database = req.result;
                });
            },
            openTxn: function(mode, storeName) {
                const txn = this._database.transaction([storeName], mode);
                const store = txn.objectStore(storeName);
                return Promise.resolve(store);
            },
            _createStores: function(db) {
                db.createObjectStore("foos", {keyPath: ["id"]});
            }
        };

        function getAll(store) {
            const request = store.openCursor();
            const results = [];
            return new Promise(function(resolve, reject) {
                request.onsuccess = function(event) {
                    const cursor = event.target.result;
                    if(cursor) {
                        results.push(cursor.value);
                        cursor.continue();
                    } else {
                        resolve(results);
                        Promise.flushQueue && Promise.flushQueue();
                    }
                };
                request.onerror = function(e) {
                    reject(new Error("IDB request failed: " + e.target.error.message));
                    Promise.flushQueue && Promise.flushQueue();
                };
            });
        }

        async function main() {
            try {
                let storage = new Storage("idb-promises");
                await storage.open();
                const store = await storage.openTxn("readwrite", "foos");
                store.clear();
                store.add({id: 5, name: "foo"});
                store.add({id: 6, name: "bar"});
                console.log("all1", await getAll(store));
                store.add({id: 7, name: "bazzz"});
                console.log("all2", await getAll(store));
            } catch(err) {
                console.error(err.message + ": " + err.stack);
            };
        }
        main();


        /*
        
        we basically want something like this for IE11/Win7:
            
            return new Promise(function (resolve, reject) {
                req.onsuccess = function() {
                    resolve(req);
                    Promise?.flushQueue();
                };
                req.onerror = function(e) {
                    reject(new Error("IDB request failed: " + e.target.error.message));
                    Promise?.flushQueue();
                };
            });

        we don't have this problem on platforms with a native promise implementation, so we can just have our own (forked) promise polyfill? 
         */
    </script>
</body>
</html>
 
